/*
 * Copyright (c) United Binary LLC.  All rights reserved.
 * 
 * This code is licensed under the MIT License
 * 
 * SEE: http://harnessit.codeplex.com/license
 * 
 */
using System;
using System.Diagnostics;
using System.Windows.Forms;

namespace UnitedBinary.Core.Windows.Forms.Persistence
{
	/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/Class/*'/>
	public abstract class PersistentWindowState
	{
		private string widthValue	= "Width";
		private string heightValue	= "Height";
		private string topValue		= "Top";
		private string leftValue	= "Left";
		private string stateValue	= "State";
		private FormWindowState state = FormWindowState.Normal;
		private Form f;

		private string keyPath = string.Empty;

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/width/*'/>
		protected int width	= 600;
		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/height/*'/>
		protected int height = 400;
		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/top/*'/>
		protected int top = 50;
		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/left/*'/>
		protected int left = 50;

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/ctor/*'/>
		public PersistentWindowState(Form form, string subKeyBaseName)
		{
			if (subKeyBaseName == null || subKeyBaseName.Length == 0)
			{
				System.ArgumentException e = new
					System.ArgumentException("Invalid SubKeyBaseName", "SubKeyBaseName");
				e.Source = "PersistantWindowState class";
				throw e;
			}

			if (form == null)
			{
				System.ArgumentException e = new System.ArgumentException("Invalid Form form", "form");
				e.Source = "PersistantWindowState class";
				throw e;
			}
			f = form;

			char[] chars = {'\\'};
			subKeyBaseName = subKeyBaseName.TrimStart(chars);
			subKeyBaseName = subKeyBaseName.TrimEnd(chars);
			keyPath = "Software\\" + subKeyBaseName + "\\" + "PersistantWindowState";

			Debug.WriteLine("PersistantWindowState: Using registry key: HKEY_CURRENT_USER\\" + keyPath);

			width	= form.Width;
			height	= form.Height;
			left	= form.Left;
			top		= form.Top;
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/Width/*'/>
		public int Width
		{
			get
			{
				try
				{
					Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath);
					width = (int)key.GetValue(widthValue, width);

					Debug.WriteLine("PersistantWindowState: Read Width from registry: " + width);
				}
				catch
				{
					Debug.WriteLine("PersistantWindowState Warning: Could not read registry key, width has never been set?");
					Debug.WriteLine("PersistantWindowState Warning: Using default value " + width);
				}

				return width;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyPath);
				key.SetValue(widthValue, value);
				Debug.WriteLine("PersistantValues: Wrote Width to registry: " + value);
			}
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/Height/*'/>
		public int Height
		{
			get
			{
				try
				{
					Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath);
					height = (int)key.GetValue(heightValue, height);

					Debug.WriteLine("PersistantWindowState: Read Height from registry: " + height);
				}
				catch
				{
					Debug.WriteLine("PersistantWindowState Warning: Could not read registry key, Height has never been set?");
					Debug.WriteLine("PersistantWindowState Warning: Using default value " + height);
				}

				return height;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyPath);
				key.SetValue(heightValue, value);
				Debug.WriteLine("PersistantValues: Wrote Height to registry: " + value);
			}
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/Top/*'/>
		public int Top
		{
			get
			{
				try
				{
					Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath);
					top = (int)key.GetValue(topValue);

					Debug.WriteLine("PersistantWindowState: Read Top from registry: " + top);
				}
				catch
				{
					Debug.WriteLine("PersistantWindowState Warning: Could not read registry key, Top has never been set?");
					Debug.WriteLine("PersistantWindowState Warning: Using default value " + top);
				}

				return top;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyPath);
				key.SetValue(topValue, value);
				Debug.WriteLine("PersistantValues: Wrote Top to registry: " + value);
			}
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/Left/*'/>
		public int Left
		{
			get
			{
				try
				{
					Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath);
					left = (int)key.GetValue(leftValue);

					Debug.WriteLine("PersistantWindowState: Read Left from registry: " + left);
				}
				catch
				{
					Debug.WriteLine("PersistantWindowState Warning: Could not read registry key, Left has never been set?");
					Debug.WriteLine("PersistantWindowState Warning: Using default value " + left);
				}

				return left;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyPath);
				key.SetValue(leftValue, value);
				Debug.WriteLine("PersistantValues: Wrote Left to registry: " + value);
			}
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/WindowState/*'/>
		public FormWindowState WindowState
		{
			get
			{
				string wndState = string.Empty;
				try
				{
					Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyPath);
					wndState = (string)key.GetValue(stateValue, "Normal");

					Debug.WriteLine("PersistantWindowState: Read state from registry: " + wndState);
					state = GetStateFromString(wndState);
				}
				catch
				{
					Debug.WriteLine("PersistantWindowState Warning: Could not read registry key, WindowState has never been set?");
					Debug.WriteLine("PersistantWindowState Warning: Using default value " + GetStringFromState(state));
				}

				return state;
			}
			set
			{
				Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyPath);
				key.SetValue(stateValue, value);
				Debug.WriteLine("PersistantValues: Wrote WindowState to registry: " + GetStringFromState(value));
			}
		}

		private FormWindowState GetStateFromString(string s)
		{
			FormWindowState wndState = FormWindowState.Normal;
			switch (s)
			{
				case "Normal":
					wndState = FormWindowState.Normal;
					break;
				case "Maximized":
					wndState = FormWindowState.Maximized;
					break;
				case "Minimized":
					wndState = FormWindowState.Minimized;
					break;
			}

			return wndState;
		}

		private string GetStringFromState(FormWindowState s)
		{
			string wndState = "Normal";
			switch (s)
			{
				case FormWindowState.Normal:
					wndState = "Normal";
					break;
				case FormWindowState.Maximized:
					wndState = "Maximized";
					break;
				case FormWindowState.Minimized:
					wndState = "Minimized";
					break;
			}

			return wndState;
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/InitializeWindow/*'/>
		public void InitializeWindow()
		{
			//
			// The form is loading.  Read the dimensions from the (persistant)
			// properties of our window persisting class.
			//
			f.Width	= Width;
			f.Height= Height;
			f.Left	= Left;
			f.Top	= Top;

			// Do this last to set the size/pos THEN maximize the form.
			f.WindowState = WindowState;
		}

		/// <include file='Persistence.xml' path='/Docs/PersistentWindowState/SaveWindow/*'/>
		public void SaveWindow()
		{
			//
			// We don't want to save the form's state if it is minimized.
			//
			if (f.WindowState == FormWindowState.Minimized)
			{
				return;
			}

			// Don't record the size if the form is maximized.  Then
			// "Normal" and "Maximized" would be the same size.
			if (f.WindowState == FormWindowState.Normal)
			{
				Width	= f.Width;
				Height	= f.Height;
				Top		= f.Top;
				Left	= f.Left;
			}

			WindowState =  f.WindowState;
		}
	}
}
